#include "vector/relu.h"

#include "stdint.h"

void ReLU::forward(const std::vector<double>& input, std::vector<double> &output)
{
    input_ = input;
    output = input_;
    for(auto &item : output)
    {
        item = std::max(0.0, item);
    }
}

std::vector<double> ReLU::backward()
{
    auto derivative = input_;
    for(auto &item : derivative)
    {
        item = item > 0 ? 1.0 : 0.0;
    }
    return derivative;
}

std::vector<double> ReLU::backward(std::vector<double> &input, const std::vector<double>& output_derivative)
{
    auto d = input.size();
    std::vector<double> derivative(d);
    for(int64_t index = 0;index<d;index++)
    {
        derivative[index] = input[index] > 0 ? output_derivative[index] : 0.0;
    }
    return derivative;
}

void ReLU::forward(const std::vector<std::vector<double>>& input, std::vector<std::vector<double>> &output)
{
    input_batch_ = input;
    output = input_batch_;
    for(auto &sample : output)
    {
        for(auto &item:sample)
        {
            item = std::max(0.0, item);
        }
    }
}

std::vector<std::vector<double>> ReLU::backward(const std::vector<std::vector<double>> &output_derivative)
{
    std::vector<std::vector<double>> derivatives{};

    auto n = input_batch_.size();
    for(int64_t index = 0; index < n; index++)
    {
        auto single_devivative = backward(input_batch_[index], output_derivative[index]);
        derivatives.push_back(single_devivative);
    }
    return derivatives;
}